package sjtu.edu.cn.se.compiler11.gui;

import Semantics.Semantics;
import Semantics.SemanticsException;
import Semantics.SemanticsOverload;
import Semantics.VarSymbol;
import SyntaxTree.ASTprogram;
import SyntaxTree.ParseException;
import SyntaxTree.XYZ2parser;

import java.io.BufferedReader;
import java.io.UnsupportedEncodingException;

import java.io.*;
import java.util.ArrayList;


import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.custom.StyledText;

import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;

import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;

import org.eclipse.swt.widgets.Composite;

import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;


import org.eclipse.swt.widgets.Shell;

import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import com.cloudgarden.resource.SWTResourceManager;



import sjtu.edu.cn.se.compiler11.gui.variabletable.*;
/**
* This code was edited or generated using CloudGarden's Jigloo
* SWT/Swing GUI Builder, which is free for non-commercial
* use. If Jigloo is being used commercially (ie, by a corporation,
* company or business for any purpose whatever) then you
* should purchase a license for each developer using Jigloo.
* Please visit www.cloudgarden.com for details.
* Use of Jigloo implies acceptance of these licensing terms.
* A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR
* THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED
* LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE.
*/


public class MainWindow extends org.eclipse.swt.widgets.Composite {

	private Menu menu1;
	private MenuItem Help;
	private MenuItem Compile;
	
	private MenuItem exitMenuItem;
	private MenuItem closeFileMenuItem;
	private MenuItem saveFileMenuItem;
	private MenuItem newFileMenuItem;
	private MenuItem openFileMenuItem;

	private Menu fileMenu;
	private MenuItem fileMenuItem;
	
	private Menu formatMenu;
	private MenuItem formatMenuItem;
	private MenuItem textWrapMenuItem;
	
	private CodeEditor codeEditor;
	private SyntaxTree syntaxTree;
	
	private StyledText errorTableView;
	private StyledText semanticsErrorView;
	private StyledText overLoadingView;
	private VariableTableView variableTableView;
	
	private ToolBar toolbar;
	private Composite tool; 
	private Shell theShell;			//need to save this in order to construct CodeEditor
	private CTabFolder tabFolder;	//the table folder in below
	private static StatusBar statusBar;	//status bar, for line number
	
	
	
	private XYZ2parser parser;
	
	{
		//Register as a resource user - SWTResourceManager will
		//handle the obtaining and disposing of resources
		SWTResourceManager.registerResourceUser(this);
	}

	
	public static void setLineNumber(int line, int col)
	{
		statusBar.SetText("Line: " + String.valueOf(line));
	}
	
	public MainWindow(Composite parent, int style) {
		super(parent, style);
		theShell = (Shell)parent;
		initGUI();
	}
	
	/**
	* Initializes the GUI.
	*/
	private void initGUI() {
		try {
			theShell.setText("Untitled - My Mini Compiler V2");
			this.setSize(1280,800);
			this.setBackground(SWTResourceManager.getColor(192, 192, 192));
			GridLayout thisLayout = new GridLayout();
			thisLayout.numColumns = 2;
			this.setLayout(thisLayout);
			{			
				{
					tool = new Composite(this, SWT.NONE);		
					GridData toolLData = new GridData(GridData.FILL);
					toolLData.widthHint = 1280;
					toolLData.heightHint = 30;
					toolLData.horizontalSpan = 2;
					tool.setLayoutData(toolLData);
					
					toolbar = new ToolBar(tool, SWT.FLAT|SWT.WRAP|SWT.RIGHT |SWT.BORDER);
					toolbar.setBounds(0, 0, 700, 70);
					    			   
					//syntax analyze
				    ToolItem toolItem2 = new ToolItem(toolbar, SWT.PUSH);
				    toolItem2.setText("");
				    toolItem2.setToolTipText("Syntax Analyze");
				    toolItem2.setImage(new Image(theShell.getDisplay(),".\\resources\\profile_exc.gif"));
				    toolItem2.addSelectionListener(new SelectionListener() {
						public void widgetSelected(SelectionEvent event) {
							codeEditor.setKeyWordColor();
							
							//here is the main entry
							try {
								errorTableView.setText("");
								syntaxTree.clear();
								
								parser = new XYZ2parser(new ByteArrayInputStream(codeEditor.getText().getBytes("UTF-8")));
								ASTprogram parsertree = parser.program();
								for(int i = 0;i<parser.getExceptionList().size();i++){
									errorTableView.append(parser.getExceptionList().get(i).toString() + "\n");
							    }
								
								//syntax tree
								syntaxTree.setRootNode(parser.getRoot());
								syntaxTree.generateTree();		        
							} 
							catch (UnsupportedEncodingException e) {
								System.out.println("Encountered errors during initializing lexer.");
								System.out.println(e.getMessage());
							} 
							catch (ParseException e) {
							    System.out.println(e.getMessage()); 
							    System.out.println("Encountered errors during parsing.");
							}

	  
						}

						@Override
						public void widgetDefaultSelected(SelectionEvent arg0) {
							// TODO Auto-generated method stub
							
						}
				    });
				    
				    //semantics analyze
					ToolItem toolItem1 = new ToolItem(toolbar, SWT.PUSH);
					toolItem1.setText("");
				    toolItem1.setToolTipText("Semantics Analyze");
				    toolItem1.setImage(new Image(theShell.getDisplay(),".\\resources\\debug_exc.gif"));
				    toolItem1.addSelectionListener(new SelectionListener() {
						public void widgetSelected(SelectionEvent event) {
							codeEditor.setKeyWordColor();
							errorTableView.setText("");
							overLoadingView.setText("");
							syntaxTree.clear();
	
							try {
								errorTableView.setText("");
								semanticsErrorView.setText("");								
								syntaxTree.clear();
								
								parser = new XYZ2parser(new ByteArrayInputStream(codeEditor.getText().getBytes("UTF-8")));
								ASTprogram parsertree = parser.program();
								for(int i = 0;i<parser.getExceptionList().size();i++){
									errorTableView.append(parser.getExceptionList().get(i).toString());
							    }
								
								if (parser.getExceptionList().size() > 0)
									return;
								
								//syntax tree
								syntaxTree.setRootNode(parser.getRoot());
								syntaxTree.generateTree();	
								Semantics semantics = new Semantics();
							      
							    semantics.TypeCheckTest(parsertree);
//						      
							    ArrayList<SemanticsException> exceptions = semantics.getExceptions();
							    ArrayList<SemanticsOverload> overloads = semantics.getOverloads(); 
							    ArrayList<String> overload_message = new ArrayList<String>();
							    ArrayList<VarSymbol> vartable = semantics.getVartable();
							    System.out.println("Variable Table:");
							    for(int m = 0; m < vartable.size(); m++)
							    	variableTableView.addVarInfo(vartable.get(m).getType(), vartable.get(m).getId(), vartable.get(m).getLine());
							    	
							    for(int i = 0; i < exceptions.size(); ++i)
							    	semanticsErrorView.append(exceptions.get(i).getMessage() + "\n"); 
							
							    for(int i = 0; i < overloads.size(); ++i){
							    	  overload_message.add(overloads.get(i).getMessage());
							      }
							      for(int i = 0; i< overload_message.size(); i++){
							    	  for(int j=i+1;j<overload_message.size();j++){
							    		  if(overload_message.get(j).equals(overload_message.get(i)))
							    			  overload_message.remove(j);
							    	  }
							      }
							      for(int i = 0; i < overload_message.size(); ++i)
							    	  overLoadingView.append(overload_message.get(i) + "\n");							    
							
							} 
							catch (UnsupportedEncodingException e) {
								System.out.println("Encountered errors during initializing lexer.");
								System.out.println(e.getMessage());
							} 
							catch (ParseException e) {
							    System.out.println(e.getMessage()); 
							    System.out.println("Encountered errors during parsing.");
							}					
						}
						
						@Override
						public void widgetDefaultSelected(SelectionEvent arg0) {
							// TODO Auto-generated method stub
							
						}
					});
				    				    
				    ToolItem toolItem3 = new ToolItem(toolbar, SWT.PUSH);    
				    toolItem3.setText("");
				    toolItem3.setToolTipText("Generate Intermediate Code");
				    toolItem3.setImage(new Image(theShell.getDisplay(),".\\resources\\run_exc.gif"));
				    
				    
				    ToolItem toolItem4 = new ToolItem(toolbar, SWT.PUSH);  
				    toolItem4.setText("");
				    toolItem4.setToolTipText("Generate Assembly Code");
				    toolItem4.setImage(new Image(theShell.getDisplay(),".\\resources\\run_exc.gif"));
				    
				    ToolItem toolItem5 = new ToolItem(toolbar, SWT.PUSH);
				    toolItem5.setText("Help");
					
				}
				{
					codeEditor = new CodeEditor(this,SWT.BORDER | SWT.MULTI |SWT.V_SCROLL,theShell );
					
					GridData codeEditorLData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
					codeEditorLData.widthHint = 950;
					codeEditorLData.heightHint = 540;
					codeEditorLData.horizontalSpan = 1;
					codeEditor.setLayoutData(codeEditorLData);
					
					codeEditor.setText("");
					codeEditor.setFont(SWTResourceManager.getFont("Verdana", 12, 0, false, false));
				}
				
				{
					Composite treeComposite = new Composite(this,SWT.NONE);
					syntaxTree = new SyntaxTree(treeComposite,SWT.BORDER | SWT.H_SCROLL, theShell);
					
					GridData syntaxTreeLData = new GridData(SWT.FILL);
					syntaxTreeLData.widthHint = 290;
					syntaxTreeLData.heightHint = 540;
					syntaxTreeLData.horizontalSpan = 1;
					treeComposite.setLayoutData(syntaxTreeLData);
					
				}
				
				{
					statusBar = new StatusBar(this);
					GridData statusBarLData = new GridData(GridData.VERTICAL_ALIGN_FILL);
					statusBarLData.widthHint = 980;
					statusBarLData.heightHint = 20;
					statusBarLData.horizontalSpan = 1;
					statusBar.setLayoutData(statusBarLData);
				}
				
				{
					tabFolder = new CTabFolder(this, SWT.NONE | SWT.BORDER);   
					tabFolder.setTabHeight(20);  
					
					tabFolder.marginHeight = 5;   
					tabFolder.marginWidth = 5;   
					tabFolder.setMaximizeVisible(true);   
					tabFolder.setMinimizeVisible(true);   
					tabFolder.setUnselectedCloseVisible(true);  
					tabFolder.setSimple(false);
					
					GridData tabFolderLData = new GridData(GridData.FILL_HORIZONTAL);
					tabFolderLData.horizontalSpan = 2;
					tabFolderLData.widthHint = 1200;
					tabFolder.setLayoutData(tabFolderLData);
					Color color = new Color(null,191,205,219);
					tabFolder.setSelectionBackground(color);  
					
					//for syntax(including lexical error) error tab box
					CTabItem errorItem = new CTabItem(tabFolder, SWT.None|SWT.MULTI|SWT.V_SCROLL);   
					errorItem.setText("Parsing Errors");			
					errorItem.setImage(new Image(theShell.getDisplay(),".\\resources\\prob.gif"));
					errorTableView = new StyledText(tabFolder,  SWT.MULTI |SWT.V_SCROLL);
					errorItem.setControl(errorTableView);  
					errorTableView.setText("");
					errorItem.setControl(errorTableView);   
				//	errorTableView.addErrorInfo("The import org.eclipse.swt.custom.ExtendedModifyEvent is never used", "CodeEditor.java", 4, "Java Problem");
					
					
					//for semantics error tab box
					CTabItem tokenStreamItem = new CTabItem(tabFolder, SWT.None|SWT.MULTI|SWT.V_SCROLL);   
					tokenStreamItem.setText("Semantics Errors");			
					tokenStreamItem.setImage(new Image(theShell.getDisplay(),".\\resources\\stream.gif"));
					semanticsErrorView = new StyledText(tabFolder,  SWT.MULTI |SWT.V_SCROLL);
					semanticsErrorView.setText("");
					tokenStreamItem.setControl(semanticsErrorView);   	
					
									
					//for variables table
					CTabItem tokenCounterItem = new CTabItem(tabFolder, SWT.None|SWT.MULTI|SWT.V_SCROLL);   
					tokenCounterItem.setText("Variable Table");			
					tokenCounterItem.setImage(new Image(theShell.getDisplay(),".\\resources\\inst_ptr.gif"));
					variableTableView = new VariableTableView(tabFolder);
					tokenCounterItem.setControl(variableTableView);   		
					
					//for function overloading view
					CTabItem statementCounterItem = new CTabItem(tabFolder, SWT.None|SWT.MULTI|SWT.V_SCROLL);   
					statementCounterItem.setText("Function Overring View");			
					statementCounterItem.setImage(new Image(theShell.getDisplay(),".\\resources\\inst_ptr_top.gif"));
					overLoadingView = new StyledText(tabFolder,  SWT.MULTI |SWT.V_SCROLL);
					statementCounterItem.setControl(overLoadingView);   			
			
					tabFolder.setSelection(errorItem);
				
				}
				
															
				menu1 = new Menu(getShell(), SWT.BAR);
				getShell().setMenuBar(menu1);
				{
					fileMenuItem = new MenuItem(menu1, SWT.CASCADE);
					fileMenuItem.setText("File");
					{
						fileMenu = new Menu(fileMenuItem);
						{
							newFileMenuItem = new MenuItem(fileMenu, SWT.CASCADE);
							newFileMenuItem.setText("New");
						}
						
						{
							openFileMenuItem = new MenuItem(fileMenu, SWT.CASCADE);
							openFileMenuItem.setText("Open");
							openFileMenuItem.addSelectionListener(new SelectionListener() {
								public void widgetSelected(SelectionEvent event) {
									  FileDialog dialog = new FileDialog(theShell,SWT.OPEN);
									  dialog.setFilterNames (new String [] {"Text Files (*.txt)", "All Files (*.*)"});
									  dialog.setFilterExtensions (new String [] {"*.txt", "*.*"}); //Windows wild cards
									  dialog.setFilterPath (".\\"); //Windows path
									  String fileName = dialog.open();
									  if (fileName != null && !fileName.isEmpty())
									  {
										  File file = new File(fileName);
										  try {
											  theShell.setText(fileName + " - My Mini Compiler V1");
											  
											  codeEditor.setText("");
											  BufferedReader input = new BufferedReader (new FileReader(file)); 
											
											  String text;
											  while((text = input.readLine()) != null)  
							                        codeEditor.append(text + "\n");
																					  
										  }
										  catch (Exception e){
											  System.out.println(e.getMessage());
										  }									  
									  }
								}
								@Override
								public void widgetDefaultSelected(
										SelectionEvent arg0) {
									// TODO Auto-generated method stub
									
								}

							});	
							
						}
						
						{
							saveFileMenuItem = new MenuItem(fileMenu, SWT.CASCADE);
							saveFileMenuItem.setText("Save");
						}
						{
							closeFileMenuItem = new MenuItem(fileMenu, SWT.CASCADE);
							closeFileMenuItem.setText("Close");
							closeFileMenuItem.addSelectionListener(new SelectionListener(){

								@Override
								public void widgetDefaultSelected(
										SelectionEvent arg0) {
									// TODO Auto-generated method stub
									
								}

								
								@Override
								public void widgetSelected(SelectionEvent arg0) {
									theShell.close();
								}
								
							});
						}
						{
							exitMenuItem = new MenuItem(fileMenu, SWT.CASCADE);
							exitMenuItem.setText("Exit");
						}
						fileMenuItem.setMenu(fileMenu);
					}
				}
				
				{
					formatMenuItem = new MenuItem(menu1, SWT.CASCADE);
					formatMenuItem.setText("Format");
					{
						formatMenu = new Menu(formatMenuItem);
						{
							textWrapMenuItem = new MenuItem(formatMenu, SWT.CHECK);
							textWrapMenuItem.setText("Text Wrap");
							textWrapMenuItem.setSelection(true);
							textWrapMenuItem.addListener(SWT.Selection, new Listener() {
								@Override 
								public void handleEvent(Event arg0) {
									codeEditor.setWordWrap(textWrapMenuItem.getSelection());					        
							      }
							    });
						}
					}
					formatMenuItem.setMenu(formatMenu);
				}
				
				
				{
					Compile = new MenuItem(menu1, SWT.CASCADE);
					Compile.setText("Compile");
				}
				
				{
					Help = new MenuItem(menu1, SWT.CASCADE);
					Help.setText("Help");
				}
				
			}
			this.layout();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	* Auto-generated main method to display this 
	* org.eclipse.swt.widgets.Composite inside a new Shell.
	*/
	public static void main(String[] args) {
		Display display = Display.getDefault();
		Shell shell = new Shell(display);
		shell.setMaximized(true);
		MainWindow inst = new MainWindow(shell, SWT.NULL);
		Point size = inst.getSize();
		
		GridLayout layout = new GridLayout();
		layout.numColumns = 1;
		//layout.makeColumnsEqualWidth = true;		
		shell.setLayout(layout);
		shell.layout();
	
		
		if(size.x == 0 && size.y == 0) {
			inst.pack();
			shell.pack();
		} else {
			Rectangle shellBounds = shell.computeTrim(0, 0, size.x, size.y);
			shell.setSize(shellBounds.width, shellBounds.height);
		}
		shell.open();
		shell.setImage(new Image(display,".\\resources\\eclipse.png"));
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
	}

}
